﻿#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;


//void Func()
//	{
//		// 这⾥可以看到如果发⽣除0错误抛出异常，另外下⾯的array和array2没有得到释放。
//		// 所以这⾥捕获异常后并不处理异常，异常还是交给外⾯处理，这⾥捕获了再重新抛出去。
//		// 但是如果array2new的时候抛异常呢，就还需要套⼀层捕获释放逻辑，这⾥更好解决⽅案
//		// 是智能指针，否则代码太戳了
//		int* array1 = new int[10];
//		int* array2 = new int[10]; // 抛异常呢
//		// ...
//		try
//		{
//			int len, time;
//			cin >> len >> time;
//			cout << Divide(len, time) << endl;
//		} 
//		catch(...)
//		{
//			cout << "delete []" << array1 << endl;
//			cout << "delete []" << array2 << endl;
//			delete[] array1;
//			delete[] array2;
//			throw; // 异常重新抛出，捕获到什么抛出什么
//		} 
//		// ...
//			cout << "delete []" << array1 << endl;
//		delete[] array1;
//		cout << "delete []" << array2 << endl;
//		delete[] array2;
//	} 

template<class T>
class SmartPtr
{
public:
	// RAII
	SmartPtr(T* ptr)
		: _ptr(ptr)
	{
		cout << "SmartPtr(T* ptr) " << _ptr << endl;
	}


	~SmartPtr()
	{
		cout << "~SmartPtr() " << _ptr << endl;
		delete[] _ptr;
	} 
	// 重载运算符，模拟指针的⾏为，⽅便访问资源
		
	T& operator*()
	{
		return *_ptr;
	} 

	T* operator->()
	{
		return _ptr;
	} 

	T& operator[](size_t i)
	{
		return _ptr[i];
	}
private:
	T* _ptr;
};

double Divide(double a, double b)
{
	// 当b == 0时抛出异常
	if (b == 0)
	{
		throw "Divide by zero condition!";
	}
	else
	{
		return (double)a / (double)b;
	}
}


void Func()
{
	SmartPtr<int> sp1(new int[10]);
	SmartPtr<int> sp2(new int[10]);

	for (size_t i = 0; i < 10; i++)
	{
		sp1[i] = sp2[i] = i;
	}

	double len, time;
	cin >> len >> time;
	cout << Divide(len, time) << endl;
	
}
//	
//int main()
//{
//	try
//	{
//		Func();
//	} 
//	catch(const char* errmsg)
//	{
//		cout << errmsg << endl;
//	} 
//	catch(const exception & e)
//	{
//		cout << e.what() << endl;
//	} 
//	catch(...)
//	{
//		cout << "未知异常" << endl;
//	} 
//
//	return 0;
//}

#include <memory>

struct Date
{
	int _year;
	int _month;
	int _day;

	Date(int year = 1, int month = 1, int day = 1)
		:_year(year), _month(month), _day(day)
	{
		cout << "Date()" << this << endl;
	}

	~Date()
	{
		cout << "~Date()" << this << endl;
	}
};


//int main()
//{
//	auto_ptr<Date> ap1(new Date);
//	auto_ptr<Date> ap2(ap1);
//	cout << "-----------------------------" << endl;
//
//	unique_ptr<Date> up1(new Date);
//	unique_ptr<Date> up2(move(up1));
//	cout << "-----------------------------" << endl;
//
//	shared_ptr<Date> sp1(new Date);
//	shared_ptr<Date> sp2(sp1);
//	shared_ptr<Date> sp3(sp2);
//	cout << sp1.use_count() << endl;
//	sp1->_year++; // 1->2
//	cout << sp1->_year << endl;
//	cout << sp2->_year << endl;
//	cout << sp3->_year << endl;
//	cout << "-----------------------------" << endl;
//
//	return 0;
//}

template<class T>
void DeleteArrayFunc(T* ptr)
{
	delete[] ptr;
	cout << "-----------------------------" << endl;
}

template<class T>
class DeleteArray
{
public:
	void operator()(T* ptr)
	{
		delete[] ptr;
		cout << "-----------------------------" << endl;
	}
};

class Fclose
{
public:
	void operator()(FILE* ptr)
	{
		cout << "fclose:" << ptr << endl;
		fclose(ptr);
	}
};

//int main()
//{
//	//unique_ptr<Date> up1(new Date[10]);
//	//shared_ptr<Date> sp1(new Date[10]);
//
//	// 仿函数对象做删除器
//	//unique_ptr<Date, DeleteArray<Date>> up2(new Date[5], DeleteArray<Date>());
//	// unique_ptr和shared_ptr⽀持删除器的⽅式有所不同
//	// unique_ptr是在类模板参数⽀持的，shared_ptr是构造函数参数⽀持的
//	// 这⾥没有使⽤相同的⽅式还是挺坑的
//	// 使⽤仿函数unique_ptr可以不在构造函数传递，因为仿函数类型构造的对象直接就可以调⽤
//	// 但是下⾯的函数指针和lambda的类型不可以
//
//	// 模板参数要 “类型”，函数参数要 “实例”
//	unique_ptr<Date, DeleteArray<Date>> up2(new Date[5]);
//	cout << "-----------------------------" << endl;
//	shared_ptr<Date> sp2(new Date[5], DeleteArray<Date>());
//	cout << "-----------------------------" << endl;
//
//	// 函数指针做删除器
//	unique_ptr<Date, void(*)(Date*)> up3(new Date[5], DeleteArrayFunc<Date>);
//	shared_ptr<Date> sp3(new Date[5], DeleteArrayFunc<Date>);
//
//	// lambda表达式做删除器
//	auto delArrOBJ = [](Date* ptr) {delete[] ptr; };
//	unique_ptr<Date, decltype(delArrOBJ)> up4(new Date[5], delArrOBJ);
//	shared_ptr<Date> sp4(new Date[5], delArrOBJ);
//
//	// 实现其他资源管理的删除器
//	shared_ptr<FILE> sp5(fopen("Test.cpp", "r"), Fclose());
//	shared_ptr<FILE> sp6(fopen("Test.cpp", "r"), 
//		[](FILE* ptr) 
//		{
//			cout << "fclose:" << ptr << endl;
//			fclose(ptr);
//		});
//
//
//	unique_ptr< Date[]> up7(new Date[5]);
//	cout << "-----------------------------" << endl;
//	shared_ptr< Date[]> sp7(new Date[5]);
//	cout << "-----------------------------" << endl;
//
//	return 0;
//}

//int main()
//{
//	shared_ptr<Date> sp1(new Date(2008, 8, 14));
//	shared_ptr<Date> sp2 = make_shared<Date>(2008, 8, 14);
//	auto sp3 = make_shared<Date>(2024, 9, 11);
//	shared_ptr<Date> sp4(new Date(2008, 8, 14));
//	shared_ptr<Date> sp5(sp4);
//
//	cout << sp1.get() << endl;
//	cout << sp4.get() << endl;
//
//	if (sp4)
//	{
//		cout << sp4.get() << endl;
//		cout << sp5.get() << endl;
//	}
//
//
//
//	return 0;
//}

#include "shared_ptr.h"
//int main()
//{
//	my_shared_ptr::shared_ptr<Date> sp1(new Date(2008, 8, 14));
//	my_shared_ptr::shared_ptr<Date> sp2(sp1);
//	my_shared_ptr::shared_ptr<Date> sp3 = sp1;
//
//	if (sp1)
//	{
//		cout << "sp1 is not empty" << endl;
//	}
//
//	my_shared_ptr::shared_ptr<Date> sp4(new Date[10], [](Date* ptr) {delete[] ptr; });
//	
//
//
//
//	return 0;
//}

struct ListNode
{
	int _data;
	//std::shared_ptr<ListNode> _next;
	//std::shared_ptr<ListNode> _prev;
	std::weak_ptr<ListNode> _next;
	std::weak_ptr<ListNode> _prev;
	// 这⾥改成weak_ptr，当n1->_next = n2;绑定shared_ptr时
	// 不增加n2的引⽤计数，不参与资源释放的管理，就不会形成循环引⽤了
	/*std::weak_ptr<ListNode> _next;
	std::weak_ptr<ListNode> _prev;*/
	~ListNode()
	{
		cout << "~ListNode()" << endl;
	}
};

//int main()
//{
//	std::shared_ptr<ListNode> n1(new ListNode);
//	std::shared_ptr<ListNode> n2(new ListNode);
//
//	cout << n1.use_count() << endl;
//	cout << n2.use_count() << endl;
//
//	n1->_next = n2;
//	n2->_prev = n1;
//
//
//	return 0;
//}

//int main()
//{
//	std::shared_ptr<string> sp1(new string("111111"));
//	std::shared_ptr<string> sp2(sp1);
//	std::weak_ptr<string> wp = sp1;
//	cout << wp.expired() << endl;
//	cout << wp.use_count() << endl;
//	cout << "______________________________________" << endl;
//
//	// sp1和sp2都指向了其他资源，则weak_ptr就过期了
//	sp1 = make_shared<string>("222222");
//	cout << wp.expired() << endl;
//	cout << wp.use_count() << endl;
//	cout << "______________________________________" << endl;
//
//	sp2 = make_shared<string>("333333");
//	cout << wp.expired() << endl;
//	cout << wp.use_count() << endl;
//	cout << "______________________________________" << endl;
//
//	wp = sp1;
//	//std::shared_ptr<string> sp3 = wp.lock();
//	auto sp3 = wp.lock();
//	cout << wp.expired() << endl;
//	cout << wp.use_count() << endl;
//	*sp3 += "###";
//	cout << *sp1 << endl;
//	return 0;
//}